/*
 * XQRunnerOptionPane.java
 */
package xq.runner;

import java.awt.GridBagConstraints;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import xq.api.XQVariable;
import xq.api.XQuery;
import xq.session.SessionFactory;
import xq.swing.InputPanel;
import xq.swing.OptionDialog;
import xq.swing.event.DocumentAdapter;
import xq.util.ClasspathClassLoader;
import xq.util.FileExtensionFilter;
import xq.util.PathComparator;
import xq.util.ResourceUtil;
import xq.util.resource.TextResource;
import static xq.util.ResourceUtil.getResourceNames;

/**
 *
 * @author  ThorntonRP
 */
public class XQRunnerOptionPane extends InputPanel {

	private final static long serialVersionUID = 1L;

	public static Map<XQVariable, String> showOptionPane() {
		XQRunnerOptionPane p = new XQRunnerOptionPane();
		OptionDialog dlg = new OptionDialog(null, "XQ Runner", true);
		dlg.setOptionComponent(p);
		dlg.setLocationRelativeTo(null);
		dlg.pack();
		dlg.setVisible(true);
		dlg.dispose();
		if (dlg.getOption() == OptionDialog.APPROVE_OPTION) {
			return p.variables;
		} else {
			return null;
		}
	}
	private final xq.session.Session session;
	private final Map<XQVariable, String> variables;
	private ClassLoader resourceLoader;

	public XQRunnerOptionPane() {
		session = SessionFactory.getInstance().getSession();
		variables = Collections.synchronizedMap(new LinkedHashMap<XQVariable, String>());
		initComponents();
		updateConnectionURI(true);
		updateResourcePath(true);
		updateQueryResource(true);
	}

	private void updateConnectionURI(boolean initializing) {
		String value;
		if (initializing) {
			value = session.get(Session.CONNECTION_URI_KEY);
			connectionURI.setText(value);
			connectionURI.getDocument().addDocumentListener(new DocumentAdapter() {

				@Override
				public void update(DocumentEvent e) {
					updateConnectionURI(false);
				}
			});
		} else {
			value = connectionURI.getText();
			session.put(Session.CONNECTION_URI_KEY, value);
		}
	}

	private void updateResourcePath(boolean initializing) {
		String value;
		if (initializing) {
			value = session.get(Session.RESOURCE_PATH_KEY);
			resourcePath.setText(value);
			resourcePath.getDocument().addDocumentListener(new DocumentAdapter() {

				@Override
				public void update(DocumentEvent e) {
					updateResourcePath(false);
				}
			});
		} else {
			value = resourcePath.getText();
			session.put(Session.RESOURCE_PATH_KEY, value);
		}

		resourceLoader = new ClasspathClassLoader(value);
		((DefaultComboBoxModel) queryResource.getModel()).removeAllElements();
		try {
			String[] resourcePaths = getResourceNames(new FileExtensionFilter("(?i)xq|xqy|xquery", true), resourceLoader);
			Arrays.sort(resourcePaths, new PathComparator("/", true));
			for (String resource : resourcePaths) {
				((DefaultComboBoxModel) queryResource.getModel()).addElement(resource);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}

	private void updateQueryResource(boolean initializing) {
		String value;
		if (initializing) {
			value = session.get(Session.QUERY_RESOURCE_KEY);
			queryResource.setSelectedItem(value);
			queryResource.addItemListener(new ItemListener() {

				@Override
				public void itemStateChanged(ItemEvent e) {
					if (e.getStateChange() == ItemEvent.SELECTED) {
						updateQueryResource(false);
					}
				}
			});
		} else {
			value = (String) queryResource.getSelectedItem();
			session.put(Session.QUERY_RESOURCE_KEY, value);
		}

		try {
			variables.clear();
			inputPanel.removeAll();
			variablesPanel.setVisible(false);
			TextResource textResource = ResourceUtil.getTextResource(value, resourceLoader);
			if (textResource != null) {
				XQuery query = new XQuery(textResource, resourceLoader);
				Set<XQVariable> inputVars = query.getExternalVariables();
				if (inputVars.size() > 0) {
					for (XQVariable var : inputVars) {
						variables.put(var, session.get(var.getName(), ""));
					}
					GridBagConstraints gbc = new GridBagConstraints();
					gbc.gridy = 0;
					gbc.anchor = GridBagConstraints.WEST;
					gbc.insets.left = 10;
					for (final Map.Entry<XQVariable, String> entry : variables.entrySet()) {
						if (gbc.gridy > 0) {
							gbc.insets.top = 10;
						}
						JLabel varLabel = new JLabel(entry.getKey().toString());
						final JTextField varField = new JTextField(entry.getValue());
						varField.getDocument().addDocumentListener(new DocumentAdapter() {

							@Override
							public void update(DocumentEvent e) {
								variables.put(entry.getKey(), varField.getText());
								session.put(entry.getKey().getName(), varField.getText());
							}
						});

						gbc.insets.right = 0;
						gbc.weightx = 0.0;
						gbc.fill = GridBagConstraints.NONE;
						inputPanel.add(varLabel, gbc);

						gbc.insets.right = 10;
						gbc.weightx = 1.0;
						gbc.fill = GridBagConstraints.HORIZONTAL;
						inputPanel.add(varField, gbc);

						gbc.gridy++;
					}
					gbc.weighty = 1.0;
					gbc.gridwidth = 2;
					gbc.insets.top = 0;
					inputPanel.add(new JPanel(), gbc);
					variablesPanel.setVisible(true);
				}
				clearMessages();
			}
			revalidate();
			repaint();
			packWindow();
		} catch (Exception ex) {
			add(new Message(MessageType.ERROR, queryResource.getName(), ex.toString(), ex));
		}
	}

	@SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        javax.swing.JPanel propertiesPanel = new javax.swing.JPanel();
        javax.swing.JLabel connectionLabel = new javax.swing.JLabel();
        connectionURI = new javax.swing.JTextField();
        javax.swing.JLabel resourcePathLabel = new javax.swing.JLabel();
        resourcePath = new javax.swing.JTextField();
        javax.swing.JButton browseButton = new javax.swing.JButton();
        javax.swing.JLabel xqueryResourceLabel = new javax.swing.JLabel();
        queryResource = new javax.swing.JComboBox();
        variablesPanel = new javax.swing.JPanel();
        inputPanel = new javax.swing.JPanel();

        setLayout(new java.awt.BorderLayout());

        java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("xq/runner/Bundle"); // NOI18N
        connectionLabel.setText(bundle.getString("XQRunnerOptionPane.connectionLabel.text")); // NOI18N

        connectionURI.setText(bundle.getString("XQRunnerOptionPane.connectionURI.text")); // NOI18N

        resourcePathLabel.setText(bundle.getString("XQRunnerOptionPane.resourcePathLabel.text")); // NOI18N

        resourcePath.setText(bundle.getString("XQRunnerOptionPane.resourcePath.text")); // NOI18N

        browseButton.setText(bundle.getString("XQRunnerOptionPane.browseButton.text")); // NOI18N
        browseButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                browseButtonActionPerformed(evt);
            }
        });

        xqueryResourceLabel.setText(bundle.getString("XQRunnerOptionPane.xqueryResourceLabel.text")); // NOI18N

        queryResource.setMaximumRowCount(12);

        javax.swing.GroupLayout propertiesPanelLayout = new javax.swing.GroupLayout(propertiesPanel);
        propertiesPanel.setLayout(propertiesPanelLayout);
        propertiesPanelLayout.setHorizontalGroup(
            propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(propertiesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(xqueryResourceLabel)
                    .addComponent(resourcePathLabel)
                    .addComponent(connectionLabel))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(queryResource, 0, 362, Short.MAX_VALUE)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, propertiesPanelLayout.createSequentialGroup()
                        .addComponent(resourcePath, javax.swing.GroupLayout.DEFAULT_SIZE, 277, Short.MAX_VALUE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(browseButton))
                    .addComponent(connectionURI, javax.swing.GroupLayout.DEFAULT_SIZE, 362, Short.MAX_VALUE))
                .addContainerGap())
        );
        propertiesPanelLayout.setVerticalGroup(
            propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(propertiesPanelLayout.createSequentialGroup()
                .addContainerGap(11, Short.MAX_VALUE)
                .addGroup(propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(connectionLabel)
                    .addComponent(connectionURI, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(resourcePathLabel)
                    .addComponent(browseButton)
                    .addComponent(resourcePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(propertiesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(xqueryResourceLabel)
                    .addComponent(queryResource, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
        );

        add(propertiesPanel, java.awt.BorderLayout.NORTH);

        inputPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("XQRunnerOptionPane.inputPanel.border.title"))); // NOI18N
        inputPanel.setLayout(new java.awt.GridBagLayout());

        javax.swing.GroupLayout variablesPanelLayout = new javax.swing.GroupLayout(variablesPanel);
        variablesPanel.setLayout(variablesPanelLayout);
        variablesPanelLayout.setHorizontalGroup(
            variablesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(variablesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(inputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 462, Short.MAX_VALUE)
                .addContainerGap())
        );
        variablesPanelLayout.setVerticalGroup(
            variablesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(variablesPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addComponent(inputPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 41, Short.MAX_VALUE))
        );

        add(variablesPanel, java.awt.BorderLayout.CENTER);
    }// </editor-fold>//GEN-END:initComponents

private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
	String currentDirectory = session.get(Session.CURRENT_DIRECTORY_KEY);
	JFileChooser fc = new JFileChooser();
	if (currentDirectory != null) {
		fc.setCurrentDirectory(new File(currentDirectory));
	}
	fc.setMultiSelectionEnabled(true);
	fc.setAcceptAllFileFilterUsed(false);
	fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
	fc.addChoosableFileFilter(new FileExtensionFilter("(?i)jar|zip", true, "Resource (Folder, ZIP or JAR)"));
	int option = fc.showOpenDialog(this);
	if (option == JFileChooser.APPROVE_OPTION) {
		File[] files = fc.getSelectedFiles();
		StringBuilder sb = new StringBuilder();
		String currentPath = resourcePath.getText();
		sb.append(currentPath);
		if (!currentPath.isEmpty() && !currentPath.endsWith(File.pathSeparator)) {
			sb.append(File.pathSeparator);
		}
		for (File f : files) {
			sb.append(f.getPath()).append(File.pathSeparator);
			session.put(Session.CURRENT_DIRECTORY_KEY, fc.getCurrentDirectory().getPath());
		}
		resourcePath.setText(sb.toString());
	}
}//GEN-LAST:event_browseButtonActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    javax.swing.JTextField connectionURI;
    javax.swing.JPanel inputPanel;
    javax.swing.JComboBox queryResource;
    javax.swing.JTextField resourcePath;
    private javax.swing.JPanel variablesPanel;
    // End of variables declaration//GEN-END:variables
}
